Análise venda de imóveis

Resumo

Este projeto fará uma breve análise exploratória dos dados de um dataset de venda de casas, para realizar a predição de preços de novas casas com caracteristicas semelhantes as ja vendidas

Visão geral do dataset

Verificando quantidade de registros e de colunas respectivamente do conjunto de dados

df %>% str %>% knitr::kable()
## spec_tbl_df [5,000 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ media de lucro de venda: num [1:5000] 79545 79249 61287 63345 59982 ...
##  $ media idade das casas  : num [1:5000] 5.68 6 5.87 7.19 5.04 ...
##  $ media numero de salas  : num [1:5000] 7.01 6.73 8.51 5.59 7.84 ...
##  $ media numero de quartos: num [1:5000] 4.09 3.09 5.13 3.26 4.23 4.04 3.41 2.42 2.3 6.1 ...
##  $ populacao da regiao    : num [1:5000] 23087 40173 36882 34310 26354 ...
##  $ valor da casa          : num [1:5000] 1059034 1505891 1058988 1260617 630943 ...
##  $ endereco               : chr [1:5000] "208 Michael Ferry Apt. 674\nLaurabury, NE 37010-5101" "188 Johnson Views Suite 079\nLake Kathleen, CA 48958" "9127 Elizabeth Stravenue\nDanieltown, WI 06482-3489" "USS Barnett\nFPO AP 44820" ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   `Avg. Area Income` = col_double(),
##   ..   `Avg. Area House Age` = col_double(),
##   ..   `Avg. Area Number of Rooms` = col_double(),
##   ..   `Avg. Area Number of Bedrooms` = col_double(),
##   ..   `Area Population` = col_double(),
##   ..   Price = col_double(),
##   ..   Address = col_character()
##   .. )

|| || || ||

df %>% head(4) %>% knitr::kable()
media de lucro de venda media idade das casas media numero de salas media numero de quartos populacao da regiao valor da casa endereco
79545.46 5.682861 7.009188 4.09 23086.80 1059034 208 Michael Ferry Apt. 674
Laurabury, NE 37010-5101
79248.64 6.002900 6.730821 3.09 40173.07 1505891 188 Johnson Views Suite 079
Lake Kathleen, CA 48958
61287.07 5.865890 8.512727 5.13 36882.16 1058988 9127 Elizabeth Stravenue
Danieltown, WI 06482-3489
63345.24 7.188236 5.586729 3.26 34310.24 1260617 USS Barnett
FPO AP 44820

Visualizando a distribuição de preços das casas por quantidade de quartos

plot_ly(data = df, x=~`media numero de quartos`, y=~`valor da casa`, type = "scatter") %>%
layout(xaxis=list(title="Numero de quartos"), yaxis=list(title="Valor da casa"))

OBS: Não há grande variação de preço por numero de quartos, mas da pra perceber que casas que contém em media 2 quartos, são um pouco mais baratas em seu valor máximo


Visualizando a distribuição de preços das casas por quantidade de salas

plot_ly(data = df, x=~`media numero de salas`, y=~`valor da casa`, type = "scatter", marker=list(color="seagreen"))

OBS: obviamente, quanto maior a quantidade de salas, maior o preço da casa, em alguns poucos casos, casas com numero menor de salas sao mais caras

OBS 2: Também é possivel notar que a grande maioria das casas possuem entre 6 a 8 salas


Visualizando a distribuição de salas por quantidade de quartos

plot_ly(data=df, x=~`media numero de quartos`, y=~`media numero de salas`, type="scatter", marker=list(color="darkmagenta"))

OBS: Podemos ver que todas as casas com 5 quartos ou mais, possuem no mínimo 7 salas

OBS 2: Também observamos que casas com 2 quartos, possuem no maximo 7 salas


Visualizando distribuição do preço da casa baseado pela idade da mesma

plot_ly(data=df, x=~`media idade das casas`, y=~`valor da casa`, type="scatter", marker=list(color="darkcyan"))

OBS: E mais uma amostra linear onde indica que, quanto mais velha a casa, maior o seu valor


Visualizando distribuição de preços da casa por tamanho da população da região

plot_ly(data=df, x=~`populacao da regiao`, y=~`valor da casa`, type="scatter", marker=list(color="firebrick"))

OBS: Quanto maior a população da região, maior o valor do imóvel


Visualizando correlações entre as variáveis

ggcorr(df, label = T, hjust = 0.85)

OBS: As maiores correlações com a variavel “valor da casa” sao: populacao da regiao, idade da casa, lucro de venda e numero de salas


Machine Learning

Escolha de variáveis

Filtrando variáveis significantes para o modelo

Três modelos serão criados, o modelo1 com as variaveis lucro de venda e idade das casas.

O modelo2 com as variaveis lucro de venda, idade das casas e populacao da regiao.

O modelo3 com as variaveis lucro de venda, idade das casas, populacao da regiao e numero de salas.

modelo1 <- lm(`valor da casa` ~ -1 + `media de lucro de venda` + `media idade das casas`, data = df)
modelo2 <- lm(`valor da casa` ~ -1 + `media de lucro de venda` + `media idade das casas` + `populacao da regiao`, data = df)
modelo3 <- lm(`valor da casa` ~ -1 + `media de lucro de venda` + `media idade das casas` + `populacao da regiao` + `media numero de salas`, data = df)

Avaliando desempenho de cada modelo

Modelo1

modelo1 %>% summary
## 
## Call:
## lm(formula = `valor da casa` ~ -1 + `media de lucro de venda` + 
##     `media idade das casas`, data = df)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -959963 -188108  -13771  157647  881064 
## 
## Coefficients:
##                             Estimate Std. Error t value            Pr(>|t|)    
## `media de lucro de venda`    12.1051     0.2344   51.64 <0.0000000000000002 ***
## `media idade das casas`   69755.4803  2685.2904   25.98 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 256800 on 4998 degrees of freedom
## Multiple R-squared:  0.9599, Adjusted R-squared:  0.9599 
## F-statistic: 5.979e+04 on 2 and 4998 DF,  p-value: < 0.00000000000000022

OBS 1: Quase 96% dos dados do valor da casa, podem ser explicados pelas variáveis preditoras escolhidas

OBS 2: Também e perceptivel que a margem de erros das duas variáveis são proximas a zero


Modelo2

modelo2 %>% summary
## 
## Call:
## lm(formula = `valor da casa` ~ -1 + `media de lucro de venda` + 
##     `media idade das casas` + `populacao da regiao`, data = df)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -860295 -181826  -16066  147448  908911 
## 
## Coefficients:
##                             Estimate Std. Error t value            Pr(>|t|)    
## `media de lucro de venda`     9.9145     0.2382   41.63 <0.0000000000000002 ***
## `media idade das casas`   47965.8638  2681.6574   17.89 <0.0000000000000002 ***
## `populacao da regiao`         7.8613     0.3167   24.82 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 242300 on 4997 degrees of freedom
## Multiple R-squared:  0.9643, Adjusted R-squared:  0.9643 
## F-statistic: 4.497e+04 on 3 and 4997 DF,  p-value: < 0.00000000000000022

OBS 1: 96,43% dos dados do valor da casa, podem ser explicados pelas variáveis preditoras escolhidas

OBS 2: Também e perceptivel que a margem de erros das três variáveis são proximas a zero


Modelo3

modelo3 %>% summary
## 
## Call:
## lm(formula = `valor da casa` ~ -1 + `media de lucro de venda` + 
##     `media idade das casas` + `populacao da regiao` + `media numero de salas`, 
##     data = df)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -870342 -182077  -15701  148139  916097 
## 
## Coefficients:
##                             Estimate Std. Error t value             Pr(>|t|)
## `media de lucro de venda`    10.2460     0.2686  38.149 < 0.0000000000000002
## `media idade das casas`   51319.5652  2961.0686  17.331 < 0.0000000000000002
## `populacao da regiao`         8.0786     0.3269  24.715 < 0.0000000000000002
## `media numero de salas`   -7326.3875  2750.6482  -2.664              0.00776
##                              
## `media de lucro de venda` ***
## `media idade das casas`   ***
## `populacao da regiao`     ***
## `media numero de salas`   ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 242100 on 4996 degrees of freedom
## Multiple R-squared:  0.9643, Adjusted R-squared:  0.9643 
## F-statistic: 3.377e+04 on 4 and 4996 DF,  p-value: < 0.00000000000000022

OBS 1: Não há diferença se comparado ao modelo dois no que diz respeito a explicação dos dados

OBS 2: É notavel que a variavel “numero de salas” tem uma margem de erro consideravelmente maior que as outras 3 variaveis


Visualizando o desempenho das predições dos 3 modelos

Será comparado os resultados estimados com os resultados originais em um gráfico de dispersão para medir a linearidade das predições com os dados reais..

Predições do modelo 1

pred1 <- tibble(dadosReais=df$`valor da casa`, predicoes=modelo1$fitted.values, residuosPadronizados=rstandard(modelo1))

plot_ly(data=pred1, x=~dadosReais, y=~predicoes, type = "scatter", marker=list(color="brown"))

OBS: Criado com as variáveis independentes: media de lucro de venda e media idade das casas


Predições do modelo 2

pred2 <- tibble(N=1:5000, dadosReais=df$`valor da casa`, predicoes=modelo2$fitted.values, residuos=modelo2$residuals, residuosPadronizados=rstandard(modelo2))

plot_ly(data=pred2, x=~dadosReais, y=~predicoes, type="scatter", marker=list(color="brown"))

OBS: Criado com as variáveis independentes: media de lucro de venda, media idade das casas e populacao da regiao


Predições do modelo 3

pred3 <- tibble(dadosReais=df$`valor da casa`, predicoes=modelo3$fitted.values, residuosPadronizados=rstandard(modelo3))

plot_ly(data=pred3, x=~dadosReais, y=~predicoes, type="scatter", marker=list(color="brown"))

OBS: Criado com as variáveis independentes: media de lucro de venda, media idade das casas, populacao da regiao, media numero de salas


Observações sobre as predições

Claramente o modelo2 teve um desempenho melhor, justamente por possuir as duas variáveis de maior correlação com a variável valor da casa


Verificando possiveis outliers do melhor modelo

Foi filtrado todos os residuos padronizados com valor maior ou igual a 1.96, ou, menor ou igual -1.96

pred2 %>% filter(residuosPadronizados >= 1.96 | residuosPadronizados <= -1.96) %>% nrow()
## [1] 241

OBS: Dos 5 mil registros, 241 são outliers

Resumo dos resíduos padronizados

rstandard(modelo2) %>% summary
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -3.55142 -0.75054 -0.06633 -0.07798  0.60871  3.75218

Comparando desempenho do modelo2 com e sem outliers

Armazenando a identificação dos outliers identificados dentro de uma variavel vetor, e usando esta variavel para remover os outliers do modelo.

outliers <- pred2 %>% filter(residuosPadronizados >= 1.96 | residuosPadronizados <= -1.96) %>% select(N)

outliers <- outliers$N

reaisSemOutliers <- df$`valor da casa`[-outliers]
predSemOutliers <- modelo2$fitted.values[-outliers]
semOutliers <- tibble(dadosReais=reaisSemOutliers, predicoes=predSemOutliers)

Visualizando o desempenho do modelo2 com e sem outliers

Modelo2 COM outliers

plot_ly(data=pred2, x=~dadosReais, y=~predicoes, type="scatter", marker=list(color="#006680"))

OBS: Extremidades mais dispersas.


Modelo2 SEM outliers

plot_ly(data=semOutliers, x=~dadosReais, y=~predicoes, type="scatter", marker=list(color="#006680"))

OBS: Extremidades mais concentradas


Individuos influentes

Dados influentes sao dados que geram impacto no modelo, que caso sejam retirados, pode haver alterações significativas.

Será feita uma verificação se há outliers influentes, para isso, será utilizada a métrica Distância de cook.

Distância de cook

A distância de cook nada mais é que uma forma de identificar se um certo dado é influente.

Para saber se o valor da distância de cook indica um ponto influente, é necessário que o o valor da distancia de cook seja próximo, igual ou maior que 1.

Ou seja, dados que possuem o valor da distância de cook semalhantes á 1.99, 1.20, 0.98, são prováveis pontos influentes. E valores da distancia de cook semlhantes á 0.03, 0.09, 0.4, são registros que NÃO são muio influentes, e que sua retirada nao deve causar muito impacto.

Visualizando distância de cook dos outliers

pred2$distanciaCook <- cooks.distance(modelo2)
outliers <- pred2 %>% filter(residuosPadronizados >= 1.96 | residuosPadronizados <= -1.96)


plot_ly(data = outliers, x=~N, y=~distanciaCook, type = "scatter")

OBS: Apesar de NÃO haver valores que indicam forte influência entre os outliers, há dois indivíduos que são um pouco mais influentes que a maioria, os registros 129 e 963. Caso tivessem valores mais elevados, não seriam removidos do modelo mesmo sendo outliers.


Tunando o modelo2

Reaplicando o modelo2 sem outliers baseado nas análises realizadas, e fazendo uma comparação com o antigo modelo2 original

outs <- pred2 %>% filter(residuosPadronizados >= 1.96 | residuosPadronizados <= -1.96) %>% select(N)
outs <- outs$N


modelo2SemOut <- lm(`valor da casa` ~ -1 + `media de lucro de venda` + `media idade das casas` + `populacao da regiao`, data = df[-outs,])

Métricas do modelo SEM outliers

modelo2SemOut %>% summary
## 
## Call:
## lm(formula = `valor da casa` ~ -1 + `media de lucro de venda` + 
##     `media idade das casas` + `populacao da regiao`, data = df[-outs, 
##     ])
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -476550 -170874  -13458  140172  470179 
## 
## Coefficients:
##                             Estimate Std. Error t value            Pr(>|t|)    
## `media de lucro de venda`     9.7726     0.2142   45.63 <0.0000000000000002 ***
## `media idade das casas`   49869.1312  2399.2677   20.79 <0.0000000000000002 ***
## `populacao da regiao`         7.8631     0.2845   27.64 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 212200 on 4756 degrees of freedom
## Multiple R-squared:  0.9725, Adjusted R-squared:  0.9725 
## F-statistic: 5.605e+04 on 3 and 4756 DF,  p-value: < 0.00000000000000022

OBS: De acordo com a métrica Multiple R-squared, 97.25% dos dados do valor da casa, podem ser explicados pelas variáveis preditoras escolhidas SEM outliers

Métricas do modelo COM outliers

modelo2 %>% summary
## 
## Call:
## lm(formula = `valor da casa` ~ -1 + `media de lucro de venda` + 
##     `media idade das casas` + `populacao da regiao`, data = df)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -860295 -181826  -16066  147448  908911 
## 
## Coefficients:
##                             Estimate Std. Error t value            Pr(>|t|)    
## `media de lucro de venda`     9.9145     0.2382   41.63 <0.0000000000000002 ***
## `media idade das casas`   47965.8638  2681.6574   17.89 <0.0000000000000002 ***
## `populacao da regiao`         7.8613     0.3167   24.82 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 242300 on 4997 degrees of freedom
## Multiple R-squared:  0.9643, Adjusted R-squared:  0.9643 
## F-statistic: 4.497e+04 on 3 and 4997 DF,  p-value: < 0.00000000000000022

OBS: De acordo com a métrica Multiple R-squared, 96.43% dos dados do valor da casa, podem ser explicados pelas variáveis preditoras escolhidas COM outliers